'''
Created on Jul 23, 2012

@author: tel
'''
import sys, os, time, numpy, site, re
site.addsitedir('../')
from collections import namedtuple

import makedb.levels as levels
from plot import SixPanelHisto
from sqlalchemy import Table, Column, Integer, ForeignKey, create_engine, event, MetaData
from sqlalchemy.orm import relationship, backref, aliased, sessionmaker, joinedload
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.pool import NullPool

def _fk_pragma_on_connect(dbapi_con, con_record):
    dbapi_con.execute('pragma foreign_keys=ON')

def LoadSession(db):
    Session = sessionmaker(bind=db)
    session = Session()
    return session

class ResiduesNotTheSameError(Exception):
    '''
    The residues present in one state don't match the residues in the other
    '''
    pass

def CompareStates(session, frame, s1, s2, property):
    #these are the SQL queries
    state1 = session.query(levels.ProtData, levels.RunData).filter(levels.ProtData.pdb==frame).filter(levels.RunData.RUN_ID==s1).one()[1]
    state2 =  session.query(levels.ProtData, levels.RunData).filter(levels.ProtData.pdb==frame).filter(levels.RunData.RUN_ID==s2).one()[1]
    
    #this prints out a header for the data
    headers = ['res','chainid','resn']
    for s in (s1, s2):
        headers += ['%s_%s' % (s1,property)]
    for header in headers:
        print '%s\t' % header,
    print '\n',
    
    #this prints out the actual data
    for res1, res2 in zip(state1.Ress, state2.Ress):
        if res1==res2:
            if res1.typ!=None:
                for val in ['res','chainid','resn']:
                    print '%s\t' % res1.__getattribute__(val),
                for res in (res1,res2):
                    print '%s\t' % res.__getattribute__(property),
                print '\n',
        else:
            #if the residues present in the two states don't have the same residue type, residue number, etc, this raises an error
            raise ResiduesNotTheSameError

def CompareFrames(session, state, f1, f2, property):
    state1 = session.query(levels.ProtData, levels.RunData).filter(levels.ProtData.pdb==f1).filter(levels.RunData.RUN_ID==state).one()[1]
    state2 =  session.query(levels.ProtData, levels.RunData).filter(levels.ProtData.pdb==f2).filter(levels.RunData.RUN_ID==state).one()[1]
    
    headers = ['res','chainid','resn']
    for s in (f1, f2):
        headers += ['%s_%s' % (f1,property)]
    for header in headers:
        print '%s\t' % header,
    print '\n',
    
    for res1, res2 in zip(state1.Ress, state2.Ress):
        if res1==res2:
            if res1.typ!=None:
                for val in ['res','chainid','resn']:
                    print '%s\t' % res1.__getattribute__(val),
                for res in (res1,res2):
                    print '%s\t' % res.__getattribute__(property),
                print '\n',
        else:
            raise ResiduesNotTheSameError

if __name__=='__main__':
    dbpath = sys.argv[1]
    db = create_engine('sqlite:///' + dbpath, poolclass=NullPool)
    event.listen(db, 'connect', _fk_pragma_on_connect)
    #db.connect().connection.create_function("regexp", 2, regexp)
    meta= MetaData(db)
    
    for level in levels.hierarchy:
        level.Table(meta=meta, db=db, reloadt=True)
    session = LoadSession(db)
    
    CompareStates(session, frame=sys.argv[2], s1=sys.argv[3], s2=sys.argv[4], property=sys.argv[5])